package src.data;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import src.domain.MailBox;
import src.domain.PostOffice;
import src.domain.User;

public class MailBoxDAO {

	private HibernateProvider provider;

	private static MailBoxDAO instance = null;

	public static MailBoxDAO getInstance() {
		if (instance == null)
			instance = new MailBoxDAO();
		return instance;
	}

	private MailBoxDAO() {
		this.provider = HibernateProvider.getInstance();
	}
	
	public MailBox getByID(MailBox mailBox){
		Criteria criteria = provider.getSession().createCriteria(MailBox.class).add(Restrictions.like("id", mailBox.getId()));
		return (MailBox) criteria.uniqueResult();
	}
	
	public MailBox getByName(MailBox mailBox){
		Criteria criteria = provider.getSession().createCriteria(MailBox.class).add(Restrictions.like("name", mailBox.getName(),MatchMode.EXACT));
		return (MailBox) criteria.uniqueResult();
	}
	
	public MailBox getByNameAndPass(MailBox mailBox){
		Criteria criteria = provider.getSession().createCriteria(MailBox.class).add(Restrictions.like("name", mailBox.getName()))
		.add(Restrictions.like("pass", mailBox.getPass()));
		return (MailBox) criteria.uniqueResult();
	}
	
	@SuppressWarnings("unchecked")
	public Set<MailBox> getAll() {

		Criteria criteria = provider.getSession().createCriteria(MailBox.class);
		Set<MailBox> set = new HashSet<MailBox>();
		set.addAll(criteria.list());
		return set;

	}
	
	@SuppressWarnings("unchecked")
	public Set<MailBox> getMailBoxes(MailBox mailBox) {

		Criteria criteria = provider.getSession().createCriteria(MailBox.class).add(Restrictions.like("name", mailBox.getName(),MatchMode.ANYWHERE));
		Set<MailBox> set = new HashSet<MailBox>();
		set.addAll(criteria.list());
		return set;

	}
	
	@SuppressWarnings("unchecked")
	public Set<User> getUsers(User user) {

		Criteria criteria = provider.getSession().createCriteria(User.class).add(Restrictions.like("name", user.getName(),MatchMode.ANYWHERE));
		Set<User> set = new HashSet<User>();
		set.addAll(criteria.list());
		return set;

	}
	
	@SuppressWarnings("unchecked")
	public Set<MailBox> getMailBoxesByPostOffice(PostOffice postOffice) {

		Query query = provider.getSession().createQuery("select m from MailBox m left join m.postOffices as p where p = :p");
		query.setParameter("p",postOffice);
		Set<MailBox> set = new HashSet<MailBox>();
		set.addAll((List<MailBox>)query.list());
		return set;

	}
	
	@SuppressWarnings("unchecked")
	public Set<MailBox> getMailBoxesByUser(User user) {

		Query query = provider.getSession().createQuery("from MailBox m where m.user = :u");
		query.setParameter("u",user);
		Set<MailBox> set = new HashSet<MailBox>();
		set.addAll((List<MailBox>)query.list());
		return set;

	}
	
	

	public void save(MailBox mailBox) {

		
		provider.getSession().save(mailBox);
		

	}

	public void saveOrUpdate(MailBox mailBox) {

		provider.getSession().saveOrUpdate(provider.getSession().merge(mailBox));
		

	}

	public void update(MailBox mailBox) {

		provider.getSession().merge(mailBox);
		
	}

	public void delete(MailBox mailBox) {
		provider.getSession().delete(mailBox);	

	}
	
	@SuppressWarnings("unchecked")
	public Set<PostOffice> getUnassignedPostOffices(MailBox mailBox) {
		//TODO: change this dummy implementation
		
		//Query query = provider.getSession().createQuery("from p in class PostOffice where p not in (:trustOffices)");
		//query.setEntity("trustOffices",(Set<PostOffice>) postOffice.getTrustOffices());
		Query query = provider.getSession().createQuery("from p in class PostOffice");
		List<PostOffice> l=query.list();
		
		for(PostOffice p:mailBox.getPostOffices())
			l.remove(p);
		
		Set<PostOffice> set = new HashSet<PostOffice>();
		set.addAll(l);
		//set.addAll(query.list());
		//query.list();
		
		/*Criteria criteria = provider.getSession().createCriteria(PostOffice.class).add(Restrictions.not(Restrictions.in("name",postOffice.getTrustOffices())));
		Set<PostOffice> set = new HashSet<PostOffice>();
		set.addAll(criteria.list());
		return set;*/
		
		return set;
	}
	
	
	
}
